<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    在学习之前要搞清楚2个东西
    主线程和任务队列与宏任务微任务是没得关系的

    宏任务：script（全局任务）seTimeout，setInterval，等
    微任务：process.nextTick，promise.then（Promise本身是同步的立即执行函数）

    当在执行一大堆js代码（也就是任务）的时候，由于js是单线程的，单线程就意味着所有任务需要排队前一个任务执行完了，才能执行后一个任务,这样太耗时了
    于是，js语言将所有的任务分为两种，一种是同步任务，一种是异步任务，
    同步任务在主线程上排队执行，异步任务不进入主线程，而是进入任务队列，等主线程的任务执行完毕，任务队列通知主线程，某个异步任务可以执行了，该任务才会进入主线程执行

    对于宏任务和微任务的运行机制如下
    在执行栈中执行一个宏任务，比如执行script代码，或者执行定时器，都是执行宏任务，执行过程中遇到微任务，将微任务添加微任务队列中
    比如遇到promise，就会将promise.then()对到微任务队列中，这里要注意，new Promise()，传给Promise的那个函数可不是异步任务，他其实是同步任务。Promise本身是同步的立即执行函数
    当前宏任务执行完成，也就是所有script的同步代码以及宏任务的定时器，
    立即执行微任务队列中的任务，当前微任务队列中的任务执行完毕，开启下一次事件循环执行下一次宏任务

    这里要搞清楚一件事情，promise.then函数中的代码先执行，定时器回到函数中的代码后执行，因为promise.then是在微任务队列，定时器的回调函数是下一次宏任务，并不是跟promise.then平级的微任务


    总结一下：
    script同步代码，定时器都是执行宏任务，只是在执行宏任务的时候区分同步任务还是异步任务，script代码也就是宏任务直接在主线程中执行了
    而定时器也是宏任务，但是执行这个定时器宏任务的时候把它丢到任务队列中去了，然后script同步代码执行完毕之后，任务队列的定时器宏任务进入主线程执行
    这里执行可不是执行定时器的回调函数，就是很单纯的开启一个定时器事件而已，宏任务执行完了，开始执行微任务，就执行promise.then中的函数
    微任务执行完毕，又开始执行下一个宏任务，也就是执行定时器的那个回调函数，回调函数放在主线程中执行，没得微任务了，所以就结束了整个执行过程。


    <script>
        console.log(1)
        setTimeout(() => {
            console.log(2)
            process.nextTick(() => {
                console.log(3)
            })
            new Promise((resolve) => {
                console.log(4)
                resolve()
            }).then(() => {
                console.log(5)
            })
        })
        // process.nextTick(() => {
        //     console.log(6)
        // })
        //优先级process.nextTick 高于 Promise。
        new Promise((resolve) => {
            console.log(7)
            resolve()
        }).then(res => {
            console.log(8)
        })
        process.nextTick(() => {
            console.log(6)
        })
        setTimeout(() => {
            console.log(9)
            process.nextTick(() => {
                console.log(10)
            })
            new Promise((resolve) => {
                console.log(11)
                resolve()
            }).then(res => {
                console.log(12)
            })
        })

        //执行顺序：1 7 6 8 2 4 3 5 9 11 10 12
        //当前顺序来自node的运行环境，node中才有process，
        //这里要注意，其实执行了3次循环
        // 第一次宏任务->微任务->第一个定时器回到函数中的宏任务->第一个定时器函数中的微任务->第二个定时器回到函数中的宏任务->第二个定时器回到函数中的微任务
        //以上才是他的执行顺序
    </script>
    <script>
        setTimeout(() => {
            console.log(1)
            new Promise((resolve) => {
                console.log(2)
                resolve()
            }).then(() => {
                console.log(3)
            })
        })

        async function async1() {
            console.log(4);
            await async2()
            console.log(5)
        }
        async function async2() {
            console.log(6)
        }

        console.log(7);
        async1();
        console.log(8)


//先执行宏任务，同步任务打印7，然后这执行async1函数，肯定接着打印4，然后又执行async2，所以打印6，然后打印8
//以上其实都是同步任务，Promise本身是同步的立即执行函数，也就是说传递给promise的那个函数其实是同步的
//现在async，await实际上是Promise的语法糖。那么async函数中在await之前的代码都会在主线程中依次执行的
// await会把await下面的代码变成微任务，所以执行微任务，拿到await async2()的结果，然后打印5
//最后开启下一个任务，执行宏任务，打印1，打印2，执行微任务打印3
    </script>



    <script>
        console.log('=============')
        console.log(1)
        setTimeout(()=>{
            console.log(2)
            Promise.resolve().then(()=>{
                console.log(3)
            })
        },0)
        new Promise(function(resolve,reject){
            console.log(4)
            setTimeout(function(){
                console.log(5)
                resolve(6)
            },0)
        }).then(res=>{
            console.log(7)
            setTimeout(()=>{
                console.log(res)
            },0)
        })
        // 1 4 2 3 5 7 6
    </script>

</body>

</html>